package pe.gob.inei.fx.lib.component
{
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.text.TextLineMetrics;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;
	
	import mx.containers.HBox;
	import mx.containers.Panel;
	import mx.controls.Button;
	import mx.controls.Image;
	import mx.core.EdgeMetrics;
	import mx.core.FlexVersion;
	import mx.core.UIComponent;
	import mx.core.UITextFormat;
	import mx.core.mx_internal;
	import mx.events.ChildExistenceChangedEvent;
	import mx.events.CloseEvent;
	import mx.events.FlexEvent;
	import mx.events.IndexChangedEvent;
	import mx.events.MoveEvent;
	import mx.events.ResizeEvent;
	
	import pe.gob.inei.fx.lib.component.events.SuperPanelEvent;
		
	use namespace mx_internal;
	
	[Event(name="maximize", type="pe.gob.inei.fx.lib.component.events.SuperPanelEvent")]
	[Event(name="minimize", type="pe.gob.inei.fx.lib.component.events.SuperPanelEvent")]
	[Event(name="restore", type="pe.gob.inei.fx.lib.component.events.SuperPanelEvent")]
	[Event(name="close", type="mx.events.CloseEvent")]
	
	[Event(name="dragStart", type="pe.gob.inei.fx.lib.component.events.SuperPanelEvent")]
	[Event(name="drag", type="pe.gob.inei.fx.lib.component.events.SuperPanelEvent")]
	[Event(name="dragEnd", type="pe.gob.inei.fx.lib.component.events.SuperPanelEvent")]
	
	[Event(name="resizeStart", type="pe.gob.inei.fx.lib.component.events.SuperPanelEvent")]
	[Event(name="resizeEnd", type="pe.gob.inei.fx.lib.component.events.SuperPanelEvent")]
	
	[Style(name="resizeGripSkin", type="Class", inherit="no")]
	[Style(name="actionAlpha", type="Number", format="Length", inherit="no")]
	[Style(name="minimizeButtonStyleName", type="String", inherit="no")]
	[Style(name="maximizeButtonStyleName", type="String", inherit="no")]
	[Style(name="closeButtonStyleName", type="String", inherit="no")]
	[Style(name="inactiveHeaderColors", type="Array", inherit="no")]
	[Style(name="inactiveHighlightAlphas", type="Array", inherit="no")]
	[Style(name="inactiveFooterColors", type="Array", inherit="no")]
	[Style(name="inactiveBorderColor", type="uint", format="Color", inherit="no")]
	[Style(name="inactiveBorderAlpha", type="Number", format="Length", inherit="no")]
	[Style(name="inactiveTitleStyleName", type="String", inherit="no")]
	[Style(name="inactiveShadowDistance", type="Number", format="Length", inherit="no")]
	
	public class SuperPanel extends Panel {
	
		static public const VERSION:uint = 0x01004002;
		
		static private const DEFAULT_ACTION_ALPHA:Number = 1;
		static private const SAVED_STYLES:Array = ["moveEffect", "resizeEffect"];
		static private const SAVED_PROPERTIES:Array = ["alpha"];
		static private const INDEX_BASED_STYLES:Array = ["headerColors", "footerColors", "borderColor",
														"borderAlpha", "highlightAlphas", "titleStyleName",
														"shadowDistance"];
		static private const SIZE_RATIO_FORMAT:RegExp = 
		/^(?!^0*$)(?!^0*\.0*$)^\d{1,2}(\.\d{1,2})?\:(?!0*$)(?!0*\.0*$)\d{1,2}(\.\d{1,2})?$/;
		
		static private var TRANSITION_END_WAIT:Number = 500;

		public function SuperPanel() {
			super();
			this.addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
			this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
			this.addEventListener(MoveEvent.MOVE, moveAndResizeHandler);
			this.addEventListener(ResizeEvent.RESIZE, moveAndResizeHandler);
			this.addEventListener(FlexEvent.REMOVE, removedHandler);
			
			_showCloseButton = false;
			preserveOriginalIndexBasedStyles();
		}
		
		private var _allowClose:Boolean = false;
		
		[Bindable]
		public function set allowClose(value:Boolean):void {
			if (_allowClose == value)
				return;
			
			_allowClose = value;
			invalidateProperties();
		}
		
		public function get allowClose():Boolean {
			return _allowClose;
		}
		
		private var _allowMaximize:Boolean = false;

		[Bindable]
		public function set allowMaximize(value:Boolean):void {
			if (_allowMaximize == value)
				return;
			
			_allowMaximize = value;
			invalidateProperties();
		}
		
		public function get allowMaximize():Boolean {
			return _allowMaximize;
		}
		
		private var _allowMinimize:Boolean = false;
		
		[Bindable]
		public function set allowMinimize(value:Boolean):void {
			if (_allowMinimize == value)
				return;
			
			_allowMinimize = value;
			invalidateProperties();
		}

		public function get allowMinimize():Boolean {
			return _allowMinimize;
		}
		
		private var _allowDrag:Boolean = false;
		
		[Bindable]
		public function set allowDrag(value:Boolean):void {
			if (_allowDrag == value)
				return;
			
			_allowDrag = value;
			invalidateProperties();
		}
		
		public function get allowDrag():Boolean {
			return _allowDrag;
		}
		
		private var _allowResize:Boolean = false;
		
		[Bindable]
		public function set allowResize(value:Boolean):void {
			if (_allowResize == value)
				return;
			
			_allowResize = value;
			invalidateProperties();
		}
		
		public function get allowResize():Boolean {
		return _allowResize;
		}
		
		private var _sizeRatio:String = null;
		
		[Bindable]
		public function set sizeRatio(value:String):void {
			if (_sizeRatio == value)
				return;
			
			if (value && !SIZE_RATIO_FORMAT.test(value))
				throw new Error("sizeRatio must contain 2 numbers separated by a colon. (i.e. '2.35:3')");
			else if (value) {
				_sizeRatioWidth = parseFloat(value.split(":")[0]);
				_sizeRatioHeight = parseFloat(value.split(":")[1]);
			}
			
			_sizeRatio = value;
			if (value)
				checkSizeRatio();
		}
		
		public function get sizeRatio():String {
		return _sizeRatio;
		}
		
		public function get minimized():Boolean {
			return isMinimized;
		}

		public function get maximized():Boolean {
			return isMaximized;
		}

		protected function get canAnimate():Boolean {
			return (!activeEffects || activeEffects.length == 0);
		}
		
		// Children
		protected var buttonContainer:HBox;
		protected var closeButton:Button;
		protected var maximizeButton:Button;
		protected var minimizeButton:Button;
		protected var resizeHitBox:Image;
		
		// States
		protected var isMaximized:Boolean = false;
		protected var isMinimized:Boolean = false;
		
		// Restore dimensions
		protected var maximizeRestoreRect:Rectangle;
		protected var minimizeRestoreRect:Rectangle;

		//  Variables
		private var _originalIndexBasedStyles:Object = {};
		private var _isResizing:Boolean = false;
		private var _isDragging:Boolean = false;
		private var _originalProperties:Object;
		private var _originalStyles:Object;
		private var _resizeCursorID:int;
		private var _transitionEndInterval:Number;
		private var _resizeGripSkinChanged:Boolean = true;
		private var _closeButtonStyleChanged:Boolean = true;
		private var _maximizeButtonStyleChanged:Boolean = true;
		private var _minimizeButtonStyleChanged:Boolean = true;
		private var _indexChanged:Boolean = true;
		private var _sizeRatioWidth:Number;
		private var _sizeRatioHeight:Number;

		private function creationCompleteHandler(event:FlexEvent):void {
			if (!isPopUp)
				this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
		
			titleBar.addEventListener(MouseEvent.MOUSE_DOWN, titleBar_mouseDownHandler);
			
			titleBar.doubleClickEnabled = true;
			titleBar.addEventListener(MouseEvent.DOUBLE_CLICK, titleBar_doubleClickHandler);

			systemManager.addEventListener(Event.DEACTIVATE, stopAllHandler);
			systemManager.addEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler);
			
			if (sizeRatio)
				checkSizeRatio();
		}
		
		private function addedToStageHandler(event:Event):void {
			stage.addEventListener(Event.MOUSE_LEAVE, stopAllHandler);
			
			this.parent.addEventListener(IndexChangedEvent.CHILD_INDEX_CHANGE, parent_indexChangeHandler);
			this.parent.addEventListener(ChildExistenceChangedEvent.CHILD_ADD, parent_indexChangeHandler);
			this.parent.addEventListener(ChildExistenceChangedEvent.CHILD_REMOVE, parent_indexChangeHandler);
		}
		
		private function removedHandler(event:Event):void {
			this.removeEventListener(event.type, removedHandler);
			this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
			
			systemManager.removeEventListener(Event.DEACTIVATE, stopAllHandler);
			systemManager.removeEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler);
			systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, systemManager_mouseMoveHandler);
			
			try {
				stage.removeEventListener(Event.MOUSE_LEAVE,
				stopAllHandler);
			}
			catch (e:Error) {}
			
			try {
				this.parent.removeEventListener(IndexChangedEvent.CHILD_INDEX_CHANGE, parent_indexChangeHandler);
				this.parent.removeEventListener(ChildExistenceChangedEvent.CHILD_ADD, parent_indexChangeHandler);
				this.parent.removeEventListener(ChildExistenceChangedEvent.CHILD_REMOVE, parent_indexChangeHandler);
			}
			catch (e:Error) {}
			
			maximizeRestoreRect = null;
			minimizeRestoreRect = null;
			_originalIndexBasedStyles = null;
			_originalProperties = null;
			_originalStyles = null;
		}
		
		private function parent_indexChangeHandler(event:*):void {
			_indexChanged = true;
			
			invalidateProperties();
		}
		
		private function moveAndResizeHandler(event:*):void {
			if (!canAnimate) {
				clearInterval(_transitionEndInterval);
				_transitionEndInterval = setInterval(updateRestoreRect, TRANSITION_END_WAIT);
			}
			else if (_isDragging)
				updateRestoreRect();
		}
		
		private function titleBar_doubleClickHandler(event:MouseEvent):void {
			if (_allowMaximize)
				toggleMaximize();
		}
		
		protected function mouseDownHandler(event:MouseEvent):void {
			try {
				this.parent.setChildIndex(this, this.parent.numChildren - 1);
			}
			catch (e:Error) {}
		}
		
		private function titleBar_mouseDownHandler(event:MouseEvent):void {
			if (!allowDrag)
				return;
			
			titleBar.addEventListener(MouseEvent.MOUSE_MOVE, titleBar_mouseMoveHandler);
			titleBar.addEventListener(MouseEvent.MOUSE_UP, titleBar_mouseUpHandler);
			
			var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.DRAG_START);
			dispatchEvent(myEvent);
		}
		
		private function titleBar_mouseUpHandler(event:*):void {
			if (!allowDrag)
				return;
			
			titleBar.removeEventListener(MouseEvent.MOUSE_MOVE, titleBar_mouseMoveHandler);
			titleBar.removeEventListener(MouseEvent.MOUSE_UP, titleBar_mouseUpHandler);
			
			this.stopDrag();
			
			_isDragging = false;
			restoreOriginalProperties();
			callLater(restoreOriginalStyles);
			updateRestoreRect();
			var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.DRAG_END);
			dispatchEvent(myEvent);
		}
		
		private function titleBar_mouseMoveHandler(event:MouseEvent):void {
			if (this.width < this.parent.width) {
				if (!_isDragging) {
					preserveOriginalProperties();
					preserveOriginalStyles();

					this.clearStyle("top");
					this.clearStyle("bottom");
					this.clearStyle("left");
					this.clearStyle("right");
					
					this.alpha = getActionAlpha();
					this.startDrag(false, new Rectangle(0, 0, parent.width - this.width, parent.height - this.height));
					
					_isDragging = true;
				}
			}
			
			var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.DRAG);
			dispatchEvent(myEvent);
		}
		
		private function closeButton_clickHandler(event:MouseEvent):void {
			dispatchEvent(new CloseEvent(CloseEvent.CLOSE));
		}
		
		private function maximizeButton_clickHandler(event:MouseEvent):void {
			toggleMaximize();
		}
		
		private function minimizeButton_clickHandler(event:MouseEvent):void {
			toggleMinimize();
		}
		
		private function systemManager_mouseMoveHandler(event:MouseEvent):void {
			if (_isResizing) {
				var globalXY:Point = localToGlobal(new Point(0, 0));
				var myPt:Point = new Point(parent.width, parent.height);
				var globalParentWH:Point = parent.localToGlobal(myPt);
				
				var tmpWidth:Number;
				var tmpHeight:Number;
				var tmpMaxHeight:Number = (globalParentWH.y - globalXY.y);
				var tmpMaxWidth:Number = (globalParentWH.x - globalXY.x);
				var tmpMinWidth:Number = Math.max(UIComponent.DEFAULT_MEASURED_MIN_WIDTH, buttonContainer.width);
				var tmpMinHeight:Number = Math.max(UIComponent.DEFAULT_MEASURED_MIN_HEIGHT, this.minHeight);
				
				tmpWidth = Math.min(tmpMaxWidth, Math.max(Math.max(tmpMinWidth, this.minWidth), (stage.mouseX - globalXY.x)));
				
				if (sizeRatio) {
					checkSizeRatio(tmpWidth);
					return;
				}
				else {
					if (((stage.mouseY - globalXY.y) > this.minHeight))
						tmpHeight = Math.min(tmpMaxHeight, (stage.mouseY - globalXY.y));
				}
			
				if (!isNaN(tmpWidth))
					this.width = tmpWidth;
				
				if (!isNaN(tmpHeight))
					this.height = tmpHeight;
			}
		}
		
		private function systemManager_mouseUpHandler(event:MouseEvent):void {
			if (_isResizing) {
				_isResizing = false;
				
				restoreOriginalProperties();
				callLater(restoreOriginalStyles);
				
				systemManager.removeEventListener(MouseEvent.MOUSE_MOVE, systemManager_mouseMoveHandler);
				
				var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.RESIZE_END);
				dispatchEvent(myEvent);
			}
			
			if (_isDragging)
				titleBar_mouseUpHandler(event);
		}
		
		private function stopAllHandler(event:*):void {
			if (_isDragging)
				titleBar_mouseUpHandler(null);
			
			if (_isResizing)
				systemManager_mouseUpHandler(null);
		}
		
		private function resizeHitBox_mouseOverHandler(event:MouseEvent):void {
			if (!_allowResize || isMinimized)
				return;
			
			resizeHitBox.addEventListener(MouseEvent.MOUSE_DOWN, resizeHitBox_mouseDownHandler);
		}
		
		private function resizeHitBox_mouseOutHandler(event:MouseEvent):void {
			if (_isResizing)
				return;
		}
		
		private function resizeHitBox_mouseDownHandler(event:MouseEvent):void {
			if (!_allowResize)
				return;
			
			_isResizing = true;
			
			preserveOriginalProperties();
			preserveOriginalStyles();
			
			this.alpha = getActionAlpha();
			
			systemManager.addEventListener(MouseEvent.MOUSE_MOVE, systemManager_mouseMoveHandler);
			
			var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.RESIZE_START);
			dispatchEvent(myEvent);
		}
		
		public function minimize():void {
			if (!canAnimate)
				return;
			
			isMinimized = true;
			isMaximized = false;
			
			updateRestoreRect();
			
			if (minimizeRestoreRect)
				this.width = minimizeRestoreRect.width;
			this.height = titleBar.height;
			
			var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.MINIMIZE);
			dispatchEvent(myEvent);
		}
		
		public function minimizeRestore():void {
			if (!canAnimate)
				return;
			
			if (minimizeRestoreRect) {
				this.move(minimizeRestoreRect.x, minimizeRestoreRect.y);
				
				this.width = minimizeRestoreRect.width;
				this.height = minimizeRestoreRect.height;
			}
			else
				this.height = Math.max(titleBar.height, this.measuredMinHeight);
		
			isMinimized = false;
		
			var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.RESTORE);
			dispatchEvent(myEvent);
		}
		
		public function toggleMinimize():void {
			if (isMinimized)
				minimizeRestore();
			else
				minimize();
		}
		
		public function maximize():void {
			if (!canAnimate)
				return;
			
			isMaximized = true;
			isMinimized = false;
			
			maximizeRestoreRect = new Rectangle(this.x, this.y, this.width, this.height);
			
			this.move(0, 0);
			this.height = this.parent.height;
			this.width = this.parent.width;
			
			var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.MAXIMIZE);
			dispatchEvent(myEvent);
		}
		
		public function maximizeRestore():void {
			if (!canAnimate)
				return;
			
			if (isMinimized)
			minimizeRestore();
			else {
				var desiredHeight:Number;
				var desiredWidth:Number;
				
				if (maximizeRestoreRect) {
					desiredWidth = maximizeRestoreRect.width;
					desiredHeight = maximizeRestoreRect.height;
				}
				else {
					desiredWidth = this.minWidth;
					desiredHeight = this.minHeight;
				}
			
				if (maximizeRestoreRect)
					this.move(maximizeRestoreRect.x, maximizeRestoreRect.y);
			
				if (desiredHeight == titleBar.height) {
					desiredWidth = minimizeRestoreRect.width;
					desiredHeight = minimizeRestoreRect.height;
				}
				this.width = desiredWidth;
				this.height = desiredHeight;
			}
			
			isMaximized = false;
			
			var myEvent:SuperPanelEvent = new SuperPanelEvent(SuperPanelEvent.RESTORE);
			dispatchEvent(myEvent);
		}
		
		public function toggleMaximize():void {
			if (maximized)
				maximizeRestore();
			else
				maximize();
		}
		
		private function measureHeaderText():Rectangle {
			var textWidth:Number = 20;
			var textHeight:Number = 14;
			
			var textFormat:UITextFormat;
			var metrics:TextLineMetrics;
			
			if (titleTextField && titleTextField.text) {
				titleTextField.validateNow();
				textFormat = titleTextField.getUITextFormat();
				metrics = textFormat.measureText(titleTextField.text, false);
				textWidth = metrics.width;
				textHeight = metrics.height;
			}
			
			if (statusTextField && statusTextField.text) {
				statusTextField.validateNow();
				textFormat = statusTextField.getUITextFormat();
				metrics = textFormat.measureText(statusTextField.text, false);
				textWidth = Math.max(textWidth, metrics.width);
				textHeight = Math.max(textHeight, metrics.height);
			}
			
			return new Rectangle(0, 0, Math.round(textWidth), Math.round(textHeight));
		}
		
		protected function preserveOriginalStyles():void {
			_originalStyles = {};
			
			for (var i:int = 0; i < SAVED_STYLES.length; i++) {
				var val:* = SAVED_STYLES[i];
				try {
					_originalStyles[val] = this.getStyle(val);
					this.clearStyle(val);
				}
				catch (e:Error) {
					trace("Could not save style: " + val);
				}
			}
		}
		
		protected function restoreOriginalStyles():void {
			for (var s:String in _originalStyles) {
				try {
					this.setStyle(s, _originalStyles[s]);
					delete _originalStyles[s];
				}
				catch (e:Error) {
					trace("Could not restore style: " + s);
				}
			}
			
			_originalStyles = null;
		}
		
		protected function preserveOriginalProperties():void {
			_originalProperties = {};
			
			for (var i:int = 0; i < SAVED_PROPERTIES.length; i++) {
				var val:* = SAVED_PROPERTIES[i];
				try {
					_originalProperties[val] = this[val];
				}
				catch (e:Error) {
					trace("Could not save property: " + val);
				}
			}
		}
		
		protected function restoreOriginalProperties():void {
			for (var s:String in _originalProperties) {
				try {
					if (_originalProperties[s] is Number && !isNaN(_originalProperties[s]))
						this[s] = _originalProperties[s];
					else if (!_originalProperties[s] is Number)
						this[s] = _originalProperties[s];
				
					delete _originalProperties[s];
				}
				catch (e:Error) {
				trace("Could not restore property: " + s);
				}
			}
			
			_originalProperties = null;
		}
		
		private function preserveOriginalIndexBasedStyles():void {
			_originalIndexBasedStyles = {};
			
			for (var i:int = 0; i < INDEX_BASED_STYLES.length; i++) {
				var val:* = INDEX_BASED_STYLES[i];
				try {
					_originalIndexBasedStyles[val] = this.getStyle(val);
					this.clearStyle(val);
				}
				catch (e:Error) {
					trace("Could not save style: " + val);
				}
			}
		}
		
		private function restoreOriginalIndexBasedStyles():void {
			for (var s:String in _originalIndexBasedStyles) {
				try {
					this.setStyle(s, _originalIndexBasedStyles[s]);
				}
				catch (e:Error) {
				trace("Could not restore style: " + s);
				}
			}
		}
		
		private function applyInactiveIndexBasedStyles():void {
			for (var s:String in INDEX_BASED_STYLES) {
				var originalStyleName:String = INDEX_BASED_STYLES[s];
				var inactiveStyleName:String = originalStyleName.substr(1, (originalStyleName.length - 1));
				
				inactiveStyleName = originalStyleName.substr(0, 1).toUpperCase() + inactiveStyleName;
				inactiveStyleName = "inactive" + inactiveStyleName;
				
				this.setStyle(originalStyleName, this.getStyle(inactiveStyleName));
			}
		}
		
		private function checkSizeRatio(width:Number = NaN):void {
			try {
				var tmpWidth:Number;
				var tmpHeight:Number;
				
				if (!isNaN(width))
					tmpWidth = width;
				else
					tmpWidth = this.width;
			
				var globalXY:Point = localToGlobal(new Point(0, 0));
				var myPt:Point = new Point(parent.width, parent.height);
				var globalParentWH:Point = parent.localToGlobal(myPt);
				
				var tmpMaxHeight:Number = (globalParentWH.y - globalXY.y);
				var tmpMaxWidth:Number = (globalParentWH.x - globalXY.x);
				var tmpMinWidth:Number = Math.max(UIComponent.DEFAULT_MEASURED_MIN_WIDTH, buttonContainer.width);
				var tmpMinHeight:Number = Math.max(UIComponent.DEFAULT_MEASURED_MIN_HEIGHT, this.minHeight);
				
				var ratio:Number = _sizeRatioHeight / _sizeRatioWidth;
				tmpHeight = ratio * tmpWidth;
				
				if (tmpHeight > tmpMaxHeight) {
					tmpHeight = tmpMaxHeight;
					tmpWidth = tmpHeight / ratio;
				}
				else if (tmpHeight < tmpMinHeight) {
					tmpHeight = tmpMinHeight;
					tmpWidth = tmpHeight / ratio;
				}
				
				if (!isNaN(tmpWidth))
					this.width = tmpWidth;
				
				if (!isNaN(tmpHeight))
					this.height = tmpHeight;
			}
			catch (e:Error) {}
		}
			
		protected function updateRestoreRect():void {
			clearInterval(_transitionEndInterval);
			
			if (!canAnimate)
				return;
			
			if (!isMinimized && !maximized) {
				minimizeRestoreRect = new Rectangle(this.x, 
				this.y, 
				this.width, 
				this.height);
			}
			else if (minimizeRestoreRect != null) {
				minimizeRestoreRect.x = this.x;
				minimizeRestoreRect.y = this.y;
			}
			else {
				minimizeRestoreRect = new Rectangle(this.x, 
				this.y, 
				Math.max(this.explicitWidth, measuredMinWidth), 
				Math.max(this.explicitHeight, measuredMinHeight));
			}
		}
		
		protected function getActionAlpha():Number {
			var retVal:Number = this.getStyle("actionAlpha");
			
			if (isNaN(retVal))
				retVal = DEFAULT_ACTION_ALPHA;
			
			return retVal;
		}
		
		override protected function layoutChrome(unscaledWidth:Number, unscaledHeight:Number):void {
			super.layoutChrome(unscaledWidth, unscaledHeight);
			
			var leftPadding:Number = 5;
			
			if (resizeHitBox) {
				resizeHitBox.setActualSize( resizeHitBox.getExplicitOrMeasuredWidth(), resizeHitBox.getExplicitOrMeasuredHeight());
				resizeHitBox.move(unscaledWidth - resizeHitBox.width, unscaledHeight - resizeHitBox.height);
			}
			if (buttonContainer) {
				var hGap:Number = buttonContainer.getStyle("horizontalGap");
				var buttonWidths:Number = 0;
				var maxButtonHeight:Number = 0;
				
				for (var i:int = 0; i < buttonContainer.numChildren; i++) {
					var child:UIComponent = buttonContainer.getChildAt(i) as UIComponent;
					
					if (child.includeInLayout) {
						buttonWidths += (hGap + child.width);
						
						if (child.height > maxButtonHeight)
							maxButtonHeight = child.height;
					}
				}
		
			buttonContainer.setActualSize(buttonWidths, maxButtonHeight);
			buttonContainer.move(unscaledWidth - buttonContainer.width - leftPadding, (titleBar.height - maxButtonHeight) * 0.5);
			}
		}
		
		override public function validateDisplayList():void {
			super.validateDisplayList();
			
			if (!allowResize)
				return;
			
			var vm:EdgeMetrics = viewMetrics;
			
			if (verticalScrollBar) {
				var h:Number = unscaledHeight - vm.top - vm.bottom;
				
				verticalScrollBar.setActualSize(verticalScrollBar.width, Math.min(h - resizeHitBox.height, h - verticalScrollBar.width));
			}
			
			if (horizontalScrollBar) {
				var w:Number = unscaledWidth - vm.left - vm.right;
				
				horizontalScrollBar.setActualSize(Math.min(w - resizeHitBox.width, w - horizontalScrollBar.height), horizontalScrollBar.height);
			}
			
			if (whiteBox)
				whiteBox.visible = false;
		}
		
		override protected function createChildren():void {
			super.createChildren();
			
			if (!buttonContainer) {
				buttonContainer = new HBox();
				buttonContainer.setStyle("horizontalAlign", "right");
				buttonContainer.setStyle("verticalAlign", "middle");
				
				titleBar.addChild(buttonContainer);
			}
			
			if (!minimizeButton) {
				minimizeButton = new Button();
				minimizeButton.width = minimizeButton.height = 16;
				minimizeButton.toggle = true;
				minimizeButton.addEventListener(MouseEvent.CLICK, minimizeButton_clickHandler, false, 0, true);
				
				buttonContainer.addChild(minimizeButton);
			}
			
			if (!maximizeButton) {
				maximizeButton = new Button();
				maximizeButton.width = maximizeButton.height = 16;
				maximizeButton.toggle = true;
				maximizeButton.addEventListener(MouseEvent.CLICK, maximizeButton_clickHandler, false, 0, true);
				
				buttonContainer.addChild(maximizeButton);
			}
			
			if (!closeButton) {
				closeButton = new Button();
				closeButton.width = closeButton.height = 16;
				closeButton.addEventListener(MouseEvent.CLICK, closeButton_clickHandler, false, 0, true);
				
				buttonContainer.addChild(closeButton);
			}
			
			if (!resizeHitBox) {
				resizeHitBox = new Image();
				
				resizeHitBox.addEventListener(MouseEvent.MOUSE_OVER, resizeHitBox_mouseOverHandler, false, 0, true);
				resizeHitBox.addEventListener(MouseEvent.MOUSE_OUT, resizeHitBox_mouseOutHandler, false, 0, true);
				
				rawChildren_addChild(resizeHitBox);
			}
			
			invalidateProperties();
		}
		
		override public function styleChanged(styleProp:String):void {
			super.styleChanged(styleProp);
			
			switch (styleProp) {
				case "resizeGripSkin":
					_resizeGripSkinChanged = true;
					invalidateProperties();
					break;
				case "closeButtonStyleName":
					_closeButtonStyleChanged = true;
					invalidateProperties();
					break;
				case "maximizeButtonStyleName":
					_maximizeButtonStyleChanged = true;
					invalidateProperties();
					break;
				case "minimizeButtonStyleName":
					_minimizeButtonStyleChanged = true;
					invalidateProperties();
					break;
			}
		}
		
		override protected function commitProperties():void {
			super.commitProperties();
			
			if (closeButton) {
				closeButton.enabled = this.enabled;
				closeButton.visible = closeButton.includeInLayout = _allowClose;
				
				if (_closeButtonStyleChanged) {
					closeButton.styleName = this.getStyle("closeButtonStyleName");
					_closeButtonStyleChanged = false;
				}
			}
			if (maximizeButton) {
				maximizeButton.enabled = this.enabled;
				maximizeButton.visible = maximizeButton.includeInLayout = _allowMaximize;
				
				maximizeButton.selected = maximized;
				
				if (_maximizeButtonStyleChanged) {
					maximizeButton.styleName = this.getStyle("maximizeButtonStyleName");
					_maximizeButtonStyleChanged = false;
				}
			}
			
			if (minimizeButton) {
				minimizeButton.enabled = this.enabled;
				minimizeButton.visible = minimizeButton.includeInLayout = _allowMinimize;
				
				minimizeButton.selected = isMinimized;
				
				if (_minimizeButtonStyleChanged) {
					minimizeButton.styleName = this.getStyle("minimizeButtonStyleName");
					_minimizeButtonStyleChanged = false;
				}
			}
			if (resizeHitBox) {
				if (_resizeGripSkinChanged) {
					resizeHitBox.source = this.getStyle("resizeGripSkin");
					_resizeGripSkinChanged = false;
				}
				
				resizeHitBox.visible = (_allowResize && !isMinimized);
				
				if (this.height != 0 && (this.height == titleBar.height || maximized))
					resizeHitBox.visible = false;
				else
				resizeHitBox.visible = _allowResize;
			}
			if (_indexChanged && this.parent) {
				if (this.parent.getChildIndex(this) == (this.parent.numChildren - 1))
					restoreOriginalIndexBasedStyles();
				else
					applyInactiveIndexBasedStyles();
		
				_indexChanged = false;
			}
		
			invalidateDisplayList();
			invalidateSize();
		}
		
		override protected function measure():void {
			super.measure();
			
			var textSize:Rectangle = measureHeaderText();
			var textWidth:Number = textSize.width;
			var textHeight:Number = textSize.height;
			
			var bm:EdgeMetrics = FlexVersion.compatibilityVersion < FlexVersion.VERSION_3_0 ? borderMetrics : EdgeMetrics.EMPTY;
			textWidth += bm.left + bm.right;    
			
			var offset:Number = 5;
			textWidth += offset * 2;
			
			if (titleIconObject)
				textWidth += titleIconObject.width;
			
			if (closeButton)
				textWidth += closeButton.getExplicitOrMeasuredWidth() + 6;
			
			measuredMinWidth = Math.max(textWidth + buttonContainer.width, measuredMinWidth);
			
			measuredWidth = Math.max(textWidth + buttonContainer.width, measuredWidth);
		}
		
		override protected function startDragging(event:MouseEvent):void {}
	}
}
